/**
 * 
 */
package com.videoshare.rdfmodel;

/**
 * @author Administrator
 *
 */
import java.io.InputStream;

import com.hp.hpl.jena.db.DBConnection;
import com.hp.hpl.jena.db.IDBConnection;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.query.ResultSetFormatter;
import com.hp.hpl.jena.query.engineHTTP.*;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.ModelMaker;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.util.FileManager;
import java.sql.*;
import java.util.*;

import com.sapientia.rdfmodel.bean.*;

public class PersistentRDF 
{
//	 Static variables
    //////////////////////////////////
	
    public static final String DB = "MySQL";
    public static final int DUBLIN_CORE_METADATA = 10;
    public static final int VCARD_METADATA = 10;
    public static final String PREFIX = "PREFIX dc:    <http://purl.org/dc/elements/1.1/> " +
	 										"PREFIX vcard:   <http://www.w3.org/2001/vcard-rdf/3.0#> " +
	 										"PREFIX foaf:	<http://xmlns.com/foaf/0.1/> ";
    
    
    /* 
     * Estrae il titolo dei contenuti multimediali e il nome dell'autore.
	 * I nomi delle variabili utilizzate nelle query devono essere uguali
	 * a quelli definiti nella classe Vocabulary
	 */
    public List sparqlModel(Model model)
	{

    	
    	String querySelect = "SELECT ?dc_title ?vcard_fn " +
    			"WHERE " +    			   	
    			"{ ?y dc:creator ?x . " +
    			" ?y dc:title  ?dc_title . " + 
    			" ?x vcard:FN  ?vcard_fn . " +    	
    			"}";
    	
    	
        String queryString = PREFIX + querySelect;
        
        Query query = QueryFactory.create(queryString);
        
        // execute the query and obtain the results
        QueryExecution qe = QueryExecutionFactory.create(query,model);
        
        List resourceList = null;
        
        try
        {
        	resourceList = queryToList(qe);
	        // query results XML format
	        //System.out.println(ResultSetFormatter.asXMLString(results));
        }
        finally
        {
	        // free up resources
	        qe.close();
        }
        
        
        // query results XML format
        //ResultSetFormatter.out(System.out,results,query);
        //System.out.println(ResultSetFormatter.asXMLString(results));
        
        
        return resourceList;
       
	}
    
	/*
	 * Estrae i corsi per i quali sono disponibili dei contenuti multimediali
	 * I nomi delle variabili utilizzate nelle query devono essere uguali
	 * a quelli definiti nella classe Vocabulary
	 */
	public List sparqlCourses(Model model)
	{
		
		
		String querySelect = "SELECT DISTINCT ?dc_relation ?vcard_fn WHERE {" +
								"?y dc:creator ?x . " +
								"?y dc:relation ?dc_relation . " +
								"?x vcard:FN ?vcard_fn . " +
								"}";
		
		String queryString = PREFIX + querySelect;
		
		Query query = QueryFactory.create(queryString);
		
		// execute the query and obtain the results
		QueryExecution qe = QueryExecutionFactory.create(query,model);
		
		List resourceList = null;
        
        try
        {
        	resourceList = queryToList(qe);
	        // query results XML format
	        //System.out.println(ResultSetFormatter.asXMLString(results));
        }
        finally
        {
	        // free up resources
	        qe.close();
        }
		
		return resourceList;
		
	}
	
	/*
	 * Estrae le lezioni relative ad un corso.
	 * I nomi delle variabili utilizzate nelle query devono essere uguali
	 * a quelli definiti nella classe Vocabulary
	 */
	public List sparqlLessons(Model model, String course)
	{
		
		
		String querySelect = "SELECT ?dc_title ?dc_date ?dc_description ?dc_identifier ?vcard_fn WHERE {" +
							"?y dc:relation \"" + course.trim() + "\" . " +							
							"?y dc:identifier ?dc_identifier . " +
							"?y dc:title ?dc_title . " +
							"?y dc:description ?dc_description . " +	
							"?y dc:date ?dc_date . "	+
							"?y dc:creator ?x . " +							
							"?x vcard:FN ?vcard_fn . " +
							"}";
		
		System.out.println("Query sparqlLesson(): ");
		System.out.println(querySelect);
		System.out.println();
		String queryString = PREFIX + querySelect;
		
		Query query = QueryFactory.create(queryString);
		
		// execute the query and obtain the results
		QueryExecution qe = QueryExecutionFactory.create(query,model);
		
		List resourceList = null;
        
        try
        {
        	resourceList = queryToList(qe);
	        // query results XML format
	        //System.out.println(ResultSetFormatter.asXMLString(results));
        }
        finally
        {
	        // free up resources
	        qe.close();
        }
		
		return resourceList;
		
	}
	
	/*
	 * Estrae i dati relativi ad una lezione.
	 * I nomi delle variabili utilizzate nelle query devono essere uguali
	 * a quelli definiti nella classe Vocabulary
	 */
	public List sparqlLessonData(Model model, String lessonTitle)
	{				
		
		String querySelect = "SELECT ?dc_format ?dc_publisher ?dc_identifier WHERE {" +
							"?x dc:title  \"" + lessonTitle + "\" . " +
							"?x dc:identifier  ?dc_identifier . " +
							"?x dc:format  ?dc_format ." +
							"?x dc:publisher ?dc_publisher . " +
							"}";
		
		String queryString = PREFIX + querySelect;
		
		Query query = QueryFactory.create(queryString);
		
		// execute the query and obtain the results
		QueryExecution qe = QueryExecutionFactory.create(query,model);
		
		List resourceList = null;
        
        try
        {
        	resourceList = queryToList(qe);
	        // query results XML format
	        //System.out.println(ResultSetFormatter.asXMLString(results));
        }
        finally
        {
	        // free up resources
	        qe.close();
        }
		
		return resourceList;
		
	}
	
	private void queryToXML(QueryExecution qe)
	{
		ResultSet results = qe.execSelect();
		System.out.println(ResultSetFormatter.asXMLString(results));
		
	}
	
	/*
	 * riporta i dati del vocabolario Dublin Core in una lista 
	 */
	private List queryToList(QueryExecution qe)
	{
		List resourceList = new ArrayList();
		
		ResultSet results = qe.execSelect();
	       
		//System.out.println(ResultSetFormatter.asXMLString(results));
		
        List variableList = results.getResultVars();
  
        Iterator it = variableList.iterator();
        String [] variable = new String[DUBLIN_CORE_METADATA];
        int i = 0;
        while(it.hasNext())
        {
        	
        	variable[i] = (String) it.next();
        	System.out.println("Variable: " + variable[i]);
        	i++;
        }
        
        
        
        for ( ; results.hasNext() ; )
        {      
        	
        	// Access variables
        	QuerySolution solution = results.nextSolution() ;
        	RDFData databean = new RDFData();
        	VCARDBean vcard = new VCARDBean();
        	
        	for(int j = 0; j < i; j++)
        	{
	        	RDFNode node = solution.get(variable[j]) ; 
	        	
	        	// If you need to test the thing returned   
	        	if ( node.isLiteral() )
	        	{
	        		String variableValue = ((Literal)node).getLexicalForm();
	        		
	        		if(variable[j].equals(Vocabulary.VCARD_FN))
	        		{
	        			vcard.setFn(variableValue);
	        			databean.setCreatorFN(variableValue);
	        		}	        		
	        		if(variable[j].equals(Vocabulary.VCARD_EMAIL))
	        		{
	        			vcard.setEmail(variableValue);
	        			databean.setCreatorEmail(variableValue);
	        		}	
	        		if(variable[j].equals(Vocabulary.DC_RELATION))
	        		{
	        			databean.setCourse(variableValue);
	        		}
	        		if(variable[j].equals(Vocabulary.DC_TITLE))
	        		{
	        			databean.setTitle(variableValue);
	        		}
	        		if(variable[j].equals(Vocabulary.DC_IDENTIFIER))
	        		{
	        			databean.setIdentifier(variableValue);
	        		}
	        		
	        		if(variable[j].equals(Vocabulary.DC_DESCRIPTION))
	        		{
	        			databean.setDescription(variableValue);
	        		}
	        		if(variable[j].equals(Vocabulary.DC_FORMAT_AUDIO_MIME_TYPE))
	        		{
	        			databean.setFormat(variableValue);
	        		}
	        		if(variable[j].equals(Vocabulary.DC_PUBLISHER))
	        		{
	        			databean.setPublisher(variableValue);
	        		}
	        		if(variable[j].equals(Vocabulary.DC_DATE))
	        		{
	        			databean.setDate(variableValue);
	        		}
	        		
	        	}
	        	
	        	
	        	
        	}
        	
        	databean.setCreator(vcard);
        	resourceList.add(databean);
        }
        
		
		return resourceList;
	}
	
	/*
	 * Effettua una query SPARQL utilizzando un servizio su un server Joseki remoto
	 * via HTTP
	 */
	public List remoteQuery(String service, String queryString)
	{		
		
		Query query = QueryFactory.create(queryString);
		QueryExecution qe = QueryExecutionFactory.sparqlService(service, query);
		
		List resourceList = null;
        
        try
        {
        	resourceList = queryToList(qe);
	        
        }
        finally
        {
	       
	        qe.close();
        }
                       
        
        return resourceList;
       
	}
	
	
	
	public InputStream loadModelFromFile(String fileName)
	{
//		 use the FileManager to find the input file
        InputStream in = FileManager.get().open(fileName);
        if (in == null) {
            throw new IllegalArgumentException( "File: " + fileName + " not found");
        }
        
        // read the RDF/XML file
        //model.read( in, "" );
        return in;
	}
	
	public Model createModel(String modelName,Connection conn)
	{
		ModelMaker maker = getMaker(conn);
		
		return maker.createModel(modelName);
	}
	
	protected ModelMaker getMaker(Connection connection) 
	{
        try 
        {
           
            // Create database connection
            IDBConnection conn  = new DBConnection ( connection,DB );
            

            // Create a model maker object
            return ModelFactory.createModelRDBMaker(conn);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            
        }

        return null;
    }
	
	
}
